package cn.t.facade.sku;

import cn.t.constants.CommonConstants;
import cn.t.constants.ResponseError;
import cn.t.converter.sku.SkuDTOConverter;
import cn.t.core.exception.BizException;
import cn.t.core.facade.FacadeImpl;
import cn.t.core.mode.PageInfoDTO;
import cn.t.core.mode.PageQueryDTO;
import cn.t.dto.android.AndroidSkuDTO;
import cn.t.dto.android.AndroidSkuDetailDTO;
import cn.t.dto.sku.SkuDTO;
import cn.t.model.device.CargowaySkuDO;
import cn.t.model.device.DeviceDO;
import cn.t.model.sku.SkuDO;
import cn.t.model.user.RoleDeviceDO;
import cn.t.model.user.RoleSkuDO;
import cn.t.request.CreateSkuReq;
import cn.t.request.SkuReq;
import cn.t.service.device.CargowaySkuService;
import cn.t.service.device.DeviceService;
import cn.t.service.sku.SkuService;
import cn.t.service.user.CustomerFirmService;
import cn.t.service.user.RoleDeviceService;
import cn.t.service.user.RoleSkuService;
import cn.t.vo.andriod.AndroidSkuDetailVO;
import cn.t.vo.andriod.AndroidSkuVO;
import cn.t.vo.ent.EntAbbSkuVO;
import cn.t.vo.sku.SkuVo;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 商品表(Sku)服务编排
 *
 * @author t
 * @since 2024-05-24 10:19:35
 */
@Slf4j
@Service
@AllArgsConstructor
public class SkuFacade extends FacadeImpl<SkuDTO, SkuDO, SkuDTOConverter, SkuService> {

    private final CustomerFirmService customerFirmService;
    private final CargowaySkuService cargowaySkuService;
    private final RoleSkuService roleSkuService;
    private final RoleDeviceService roleDeviceService;
    private final DeviceService deviceService;

    public List<SkuDTO> findModelList(List<String> skus) {
        if (CollectionUtils.isEmpty(skus)) {
            return new ArrayList<>();
        }
        List<SkuDO> modelList = service.findModelList(skus);
        if (CollectionUtils.isEmpty(modelList)) {
            return new ArrayList<>();
        }

        return modelList.stream().map(converter::model2Dto).collect(Collectors.toList());
    }

    public PageInfoDTO<SkuVo> findSkuByPage(PageQueryDTO<SkuReq> req) {

        // 已绑/未绑sku
        Map<String, Integer> limitedTypeMap = new HashMap<>();
        Map<String, Integer> limitedQuantityMap = new HashMap<>();
        Map<String, Long> skuRoleSkuMap = new HashMap<>();
        if (req.getParam().getRoleId() != null) {
            List<RoleSkuDO> roleSkuDOS = roleSkuService.findByRoleId(req.getParam().getRoleId());
            List<String> boundSkuCodes = roleSkuDOS.stream().map(RoleSkuDO::getSkuCode).collect(Collectors.toList());
            if (Boolean.TRUE.equals(req.getParam().getIsBound())) {
                // 没有已绑sku直接返回
                if (CollectionUtils.isEmpty(boundSkuCodes)) {
                    return new PageInfoDTO<>(req.getPageNo(), req.getPageSize(), CommonConstants.ZERO, Collections.emptyList());
                }

                req.getParam().setSkuCodes(boundSkuCodes);
                roleSkuDOS.forEach(f -> {
                    limitedTypeMap.put(f.getSkuCode(), f.getLimitedType());
                    limitedQuantityMap.put(f.getSkuCode(), f.getLimitedQuantity());
                    skuRoleSkuMap.put(f.getSkuCode(), f.getId());
                });
            } else if (Boolean.FALSE.equals(req.getParam().getIsBound())) {
                List<RoleDeviceDO> roleDeviceDOS = roleDeviceService.findByRoleId(req.getParam().getRoleId());
                if (!CollectionUtils.isEmpty(roleDeviceDOS)){
                    List<CargowaySkuDO> deviceSkuList = cargowaySkuService.getDeviceSkuList(roleDeviceDOS.stream().map(RoleDeviceDO::getDeviceId).collect(Collectors.toList()));
                    List<String> unboundSkuCodes = deviceSkuList.stream().map(CargowaySkuDO::getSkuCode).filter(Objects::nonNull).filter(f -> !boundSkuCodes.contains(f)).distinct().collect(Collectors.toList());
                    // 没有sku直接返回
                    if (CollectionUtils.isEmpty(unboundSkuCodes)) {
                        return new PageInfoDTO<>(req.getPageNo(), req.getPageSize(), CommonConstants.ZERO, Collections.emptyList());
                    }
                    req.getParam().setSkuCodes(unboundSkuCodes);
                }else {
                    return new PageInfoDTO<>(req.getPageNo(), req.getPageSize(), CommonConstants.ZERO, Collections.emptyList());

                }


            }
        }

        List<SkuDO> list = service.querySkuPage(req, req.getSortParam().getField(), req.getSortParam().getDirection());
        if (CollectionUtils.isEmpty(list)) {
            return new PageInfoDTO<>(req.getPageNo(), req.getPageSize(), 0, null);
        }
        List<SkuVo> records = list.stream()
                .map(f -> this.converter.do2Vo(f, limitedTypeMap.get(f.getSkuCode()), limitedQuantityMap.get(f.getSkuCode()), skuRoleSkuMap.get(f.getSkuCode())))
                .collect(Collectors.toList());
        return new PageInfoDTO<>(req.getPageNo(), req.getPageSize(), service.querySkuCount(req.getParam()), records);

    }

    @Transactional
    public Boolean add(CreateSkuReq req) {
        SkuDO skuCodeDO = new SkuDO();
        skuCodeDO.setSkuCode(req.getSkuCode());
        if (service.count(skuCodeDO) > 0) {
            throw new BizException(ResponseError.SKU_EXIST, String.format(ResponseError.SKU_EXIST.getName(), req.getSkuCode()));
        }
        // 新增商品
        SkuDO skuDO = this.converter.createParam2do(req);
        service.add(skuDO);
        return true;
    }

    public SkuVo detail(String skuCode) {
        return this.converter.do2Vo(service.detail(skuCode), null, null, null);
    }

    @Transactional
    public Boolean updateStatus(String skuCode, Integer status) {
        service.updateStatus(skuCode, status);
        // 更新其他表的商品冗余信息
        SkuDO skuDO = new SkuDO();
        skuDO.setSkuCode(skuCode);
        skuDO.setStatus(status);
        cargowaySkuService.updateRedundancySkuInfo(skuDO);
        return true;
    }

    @Transactional
    public Boolean update(CreateSkuReq req) {
        SkuDO skuCodeDO = new SkuDO();
        skuCodeDO.setSkuCode(req.getSkuCode());
        if (service.count(skuCodeDO) == 0) {
            throw new BizException(ResponseError.SKU_NOT_EXIST, String.format(ResponseError.SKU_NOT_EXIST.getName(), req.getSkuCode()));
        }
        // 更新商品
        SkuDO skuDO = this.converter.createParam2do(req);
        service.update(skuDO);

        // 更新其他表的商品冗余信息
        cargowaySkuService.updateRedundancySkuInfo(skuDO);
        return true;
    }


    public List<AndroidSkuVO> getList(AndroidSkuDTO req) {
        // 根据公司查询所有设备
        List<DeviceDO> deviceDOS = deviceService.getDevicesByFirmId(req.getFirmId());
        if (CollectionUtils.isEmpty(deviceDOS)) {
            return Lists.newArrayList();
        }
        List<CargowaySkuDO> deviceSkuList = cargowaySkuService.getGroupBySku(
                deviceDOS.stream().map(DeviceDO::getId).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(deviceSkuList)) {
            return Lists.newArrayList();
        }
        return converter.do2CargowayVo(deviceSkuList);
    }

    public List<AndroidSkuDetailVO> getDetail(AndroidSkuDetailDTO req) {
        List<DeviceDO> deviceDOS = deviceService.getDevicesByFirmId(req.getFirmId());
        if (CollectionUtils.isEmpty(deviceDOS)) {
            return Lists.newArrayList();
        }
        List<AndroidSkuDetailVO> list = converter.do2CargowaySkuVO(deviceDOS);
        list.forEach(entity -> {
            List<CargowaySkuDO> cargowayVOS = cargowaySkuService.getNoAndIntervery(entity.getId(), req.getSkuCode());
            if (!CollectionUtils.isEmpty(cargowayVOS)) {
                List<AndroidSkuDetailVO.CargowayVO> cars = converter.carDo2CarVo(cargowayVOS);
                entity.setCargowayList(cars);
            }
        });
        return list.stream().filter(obj -> !CollectionUtils.isEmpty(obj.getCargowayList())).collect(Collectors.toList());
    }

    public List<EntAbbSkuVO> getAbbSku(Long firmId) {
        // 根据公司查询所有设备
        List<DeviceDO> deviceDOS = deviceService.getDevicesByFirmId(firmId);
        if (CollectionUtils.isEmpty(deviceDOS)) {
            return Lists.newArrayList();
        }
        List<CargowaySkuDO> deviceSkuList = cargowaySkuService.getGroupBySku(
                deviceDOS.stream().map(DeviceDO::getId).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(deviceSkuList)) {
            return Lists.newArrayList();
        }
        return converter.do2AbbSkuVo(deviceSkuList);
    }
    public Map<String,SkuDTO> getSkuMap(List<String> skuCodes){
      return   findModelList(skuCodes).stream().collect(Collectors.toMap(SkuDTO::getSkuCode,Function.identity()));
    }

}

